package com.xframework.filter;

import com.xframework.Base;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * Created by xuning on 2021/1/30.
 */
@Component
public class ResponseFilter implements Filter {
    private final static String RESP_JSON_BRACE_LEFT = "{";
    private final static String RESP_JSON_CODE = "\"code\":";
    private final static String RESP_JSON_RESULT = ",\"result\":";
    private final static String RESP_JSON_BRACE_RIGHT = "}";

    @Override
    public void init(FilterConfig arg) throws ServletException {
        System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ResponseFilter xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        ResponseWrapper responseWrapper = new ResponseWrapper(httpResponse);
        // 这里只拦截返回，直接让请求过去，如果在请求前有处理，可以在这里处理
        filterChain.doFilter(request, responseWrapper);
        String feign = httpRequest.getHeader(Base.FEIGN);
        byte[] resultByte = responseWrapper.getContent();
        if (feign == null) {
            int code = 0;
            String result;
            if (resultByte != null && resultByte.length > 0) {
                result = new String(resultByte, StandardCharsets.UTF_8);
                if (result.startsWith(RESP_JSON_BRACE_LEFT) || !result.startsWith(Base.DOUBLE_QUOTATION)) {
                    code = 1;
                }
            } else {
                result = Base.DOUBLE_QUOTATION + Base.DOUBLE_QUOTATION;
            }
            String json = RESP_JSON_BRACE_LEFT + RESP_JSON_CODE + code + RESP_JSON_RESULT + result + RESP_JSON_BRACE_RIGHT;
            resultByte = json.getBytes(StandardCharsets.UTF_8);
        }
        response.setContentLength(resultByte.length);//重新设置返回长度
        ServletOutputStream out = response.getOutputStream();
        out.write(resultByte);
        out.flush();
        out.close();
    }

//    @Bean
//    public FilterRegistrationBean registResponseFilter() {
//        FilterRegistrationBean<ResponseFilter> filterReg = new FilterRegistrationBean<ResponseFilter>();
//        filterReg.setFilter(new ResponseFilter());
//        filterReg.setName("ResponseFilter");
//        filterReg.setDispatcherTypes(DispatcherType.REQUEST);
//        filterReg.addUrlPatterns("/*");
//        filterReg.setEnabled(Boolean.TRUE);
//        filterReg.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
//        filterReg.setOrder(Ordered.HIGHEST_PRECEDENCE + 10);
//        return filterReg;
//    }

    private class ResponseWrapper extends HttpServletResponseWrapper {
        private ByteArrayOutputStream buffer;
        private ServletOutputStream out;

        public ResponseWrapper(HttpServletResponse httpServletResponse) {
            super(httpServletResponse);
            buffer = new ByteArrayOutputStream();
            out = new WrapperOutputStream(buffer);
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return out;
        }

        @Override
        public void flushBuffer() throws IOException {
            if (out != null) {
                out.flush();
            }
        }

        public byte[] getContent() throws IOException {
            flushBuffer();
            return buffer.toByteArray();
        }
    }

    private class WrapperOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream bos;

        public WrapperOutputStream(ByteArrayOutputStream bos) {
            this.bos = bos;
        }

        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener arg0) {
        }
    }

}
